home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 415 < prev    next >
Encoding:
Text File  |  1996-08-06  |  4.0 KB  |  138 lines

  1. Path: chronicle.mti.sgi.com!austern
  2. From: jones@cais.cais.com (Ben Jones)
  3. Newsgroups: comp.std.c++
  4. Subject: Re: Q: Generic Callbacks -- "Object->*func(...)"
  5. Date: 21 Feb 1996 09:50:36 PST
  6. Organization: Capital Area Internet Service info@cais.com 703-448-4470
  7. Approved: austern@isolde.mti.sgi.com
  8. Message-ID: <4gfdck$i0g@zippy.cais.net>
  9. References: <4fti32$p3p@bcarh8ab.bnr.ca>
  10. NNTP-Posting-Host: isolde.mti.sgi.com
  11. X-Original-Date: 21 Feb 1996 15:23:00 GMT
  12. X-Newsreader: TIN [version 1.2 PL2]
  13. X-Auth: PGPMoose V1.1 PGP comp.std.c++
  14.     iQBVAwUBMStbmEy4NqrwXLNJAQETwQIAmk+iMfjzJ9J9eWwRTysUcfjhUKnQ0U9j
  15.     JDMFC4YaVYqv0/LNp1jCF46owo3wSwrUySlSt2/eRy6hi5Rrrf56YQ==
  16.     =AlDY
  17. Originator: austern@isolde.mti.sgi.com
  18.  
  19. brian (b.c.) white (bcwhite@bnr.ca) wrote:
  20. : Does the C++ standard allow for a generic callback to be specified?
  21.  
  22. : Basically, I'd like to be able to pass an arbitrary object and function of
  23. : that object to be called at some later time.  For example:
  24.  
  25. : void DoIt(ANYOBJECT* Object, void (ANYOBJECT::*CallBack)( ...parmlist... ))
  26. : {
  27. :     [...]
  28. :     Object->*CallBack( ...parms... );
  29. :     [...]
  30. : }
  31.  
  32.  
  33. : I'd like to be able to call "DoIt" with any type of object and a pointer to
  34. : any of that object's member functions that match the 'parmlist'.  As it
  35. : stands, any object passed in would have to be in the same class hierarchy
  36. : as ANYOBJECT, thus basically requiring a unified class hierachy in order to
  37. : do this genericly.
  38.  
  39. : [snip snip]
  40.  
  41. : So...  Is this possible?
  42.  
  43.  
  44. The following kluge works on all platforms that I have tried it on
  45. including Sun, SGI, Alpha, Macintosh, PC:
  46.  
  47.     #include <stdarg.h>
  48.  
  49.     class Callback
  50.     {
  51.     public:
  52.       typedef void (Callback::*MF)();
  53.       typedef void (*F)();
  54.  
  55.       Callback(F ff=0)
  56.     {
  57.       p = 0;
  58.       f = ff;
  59.     }
  60.       Callback(void *pp,...)
  61.     {
  62.       va_list ap; va_start(ap,pp);
  63.       p=(Callback*)pp;
  64.       mf = va_arg(ap,MF);
  65.     }
  66.       virtual void operator()()
  67.     {
  68.       if (p)
  69.         (p->*mf)();
  70.       else if (f)
  71.         f();
  72.     }
  73.  
  74.     private:
  75.       Callback *p;
  76.       union { MF mf; F f; };
  77.     };
  78.  
  79. Essentially, the "Callback" class consists of an object pointer and a
  80. function pointer.  The constructors provide for two cases: a global
  81. function (which causes a null object pointer to be stored) or a paired
  82. object and member function pointer.  The parenthesis operator is
  83. overloaded so that a Callback object may be executed as though it were
  84. a function pointer.  It is declared virtual so that virtual callback
  85. functions will work properly.
  86.  
  87. Now we can set up a callback very easily:
  88.  
  89.     Callback mycallback;
  90.         ...
  91.     mycallback = function;
  92.         ...
  93.     mycallback = Callback(&object,&classname::memberfunction);
  94.         ...
  95.     mycallback();
  96.  
  97. The above class can be defined with a template or macro such that
  98. you can make variations on it for callback functions with various
  99. argument types.
  100.  
  101. It is not typesafe.  It is your responsibility to make sure that
  102. "object" and "memberfunction" are compatible.  However, as I said
  103. before, it works everywhere that I've tried it.
  104.  
  105.     ------------
  106.  
  107. A simple extension to C++ would allow for a perfectly typesafe
  108. callback scheme.  All that is necessary is that the following
  109. expressions:
  110.  
  111.     object.function
  112.     pointer->function
  113.  
  114. be LEGAL without having to be followed by ().  For them to be
  115. legal there needs to be a container which can hold the values
  116. of those expressions.  I would suggest:
  117.  
  118.     type (::*callback)(type1,type2,...)
  119.  
  120. That is, if you specify "::*" without a qualifying classname,
  121. then "callback" can accept an expression like "object.function"
  122. provided that "function" has a prototype of "type(type1,type2,..)".
  123. Simple as that.
  124.  
  125. ANSI commitee please take note.
  126.  
  127. Ben Jones
  128. Hughes Information Technology
  129. bjones@eos.hitc.com
  130. jones@cais.com
  131. ---
  132. [ To submit articles: Try just posting with your newsreader.  If that fails,
  133.                       use mailto:std-c++@ncar.ucar.edu
  134.   FAQ:    http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
  135.   Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
  136.   Comments? mailto:std-c++-request@ncar.ucar.edu 
  137. ]
  138.